package com.caishi.lkx.exam.question;

import com.caishi.lkx.exam.model.QuestionModel;
import com.zzw.common.utils.MD5Util;
import com.caishi.lkx.exam.ienum.type.QuestionSourceType;
import com.caishi.lkx.exam.ienum.type.QuestionType;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class QuestionDataProcessComposite extends AbstractQuestionDataProcess {

    public static final QuestionDataProcessComposite instance = new QuestionDataProcessComposite();


    private final SingleChoiceDataProcess singleChoiceDataProcess = new SingleChoiceDataProcess();
    private final MultipleChoiceDataProcess multipleChoiceDataProcess = new MultipleChoiceDataProcess();
    private final JudgmentDataProcess judgmentDataProcess = new JudgmentDataProcess();
    private final FillDataProcess fillDataProcess = new FillDataProcess();
    private final TextDataProcess textDataProcess = new TextDataProcess();
    private final CombinationDataProcess combinationDataProcess = new CombinationDataProcess(this);

    private QuestionDataProcessComposite() {
    }

    private Object getQuestionObject(QuestionType type) {
        if (type == QuestionType.singleChoice) return singleChoiceDataProcess;
        if (type == QuestionType.multipleChoice || type == QuestionType.indefiniteMultipleChoice) return multipleChoiceDataProcess;
        if (type == QuestionType.judgment) return judgmentDataProcess;
        if (type == QuestionType.fill) return fillDataProcess;
        if (type == QuestionType.text) return textDataProcess;
        if (type == QuestionType.combination) return combinationDataProcess;
        return null;
    }

    private AbstractQuestionDataProcess getProcess(QuestionType type) {
        return (AbstractQuestionDataProcess) getQuestionObject(type);
    }

    private Question<Object> getQuestion(QuestionType type) {
        return (Question<Object>) getQuestionObject(type);
    }

    @Override
    public String questionContentSign(QuestionModel questionModel) {
        if (questionModel.getSourceType() == QuestionSourceType.combination) {
            var sign = getProcess(questionModel.getFirstType()).questionContentSign(questionModel);
            return MD5Util.MD5Encode(sign + questionModel.getSourceId());
        }
        return getProcess(questionModel.getFirstType()).questionContentSign(questionModel);
    }

    @Override
    public boolean questionContentCheck(QuestionModel questionModel) {
        return getProcess(questionModel.getFirstType()).questionContentCheck(questionModel);
    }

    @Override
    public double computedQualityLevel(QuestionModel questionModel) {
        return getProcess(questionModel.getFirstType()).computedQualityLevel(questionModel);
    }

    @Override
    protected double computedAnswerQualityLevel(QuestionModel questionModel) {
        return getProcess(questionModel.getFirstType()).computedAnswerQualityLevel(questionModel);
    }

    @Override
    protected double computedStemQualityLevel(QuestionModel questionModel) {
        return getProcess(questionModel.getFirstType()).computedStemQualityLevel(questionModel);
    }

    @Override
    protected double computedDescQualityLevel(QuestionModel questionModel) {
        return getProcess(questionModel.getFirstType()).computedDescQualityLevel(questionModel);
    }

    @Override
    protected double computedRightAnswerQualityLevel(QuestionModel questionModel) {
        return getProcess(questionModel.getFirstType()).computedRightAnswerQualityLevel(questionModel);
    }

    public boolean userAnswerIsRight(QuestionType type, Object rightAnswer, Object userAnswer) {
        if ((type.equals(QuestionType.multipleChoice) || type.equals(QuestionType.indefiniteMultipleChoice) )&& rightAnswer instanceof String right) {
            List<String> list = new ArrayList<>();
            String pattern = "[A-Z]";
            Pattern r = Pattern.compile(pattern);
            Matcher matcher = r.matcher(right);
            matcher.results().forEach(f -> {
                list.add(f.group());
            });
            rightAnswer = list;
        }
        return getQuestion(type).userAnswerIsRight(rightAnswer, userAnswer);
    }
}
